package pl.prv.polanie.client.panels.widgets;

import java.util.List;

import pl.prv.polanie.client.Planner;
import pl.prv.polanie.client.dto.CSGroupDTO;
import pl.prv.polanie.client.dto.CSLecturerDTO;
import pl.prv.polanie.client.dto.CSRoomDTO;
import pl.prv.polanie.client.dto.CSSemestersYearGroupsDTO;
import pl.prv.polanie.client.dto.CSSubjectEventDTO;
import pl.prv.polanie.client.dto.CSVGroupDTO;
import pl.prv.polanie.client.dto.ICSDTO;
import pl.prv.polanie.client.model.Cache;
import pl.prv.polanie.client.model.CacheService;
import pl.prv.polanie.client.model.ViewDataProvider;
import pl.prv.polanie.client.panels.SchedulesList;
import pl.prv.polanie.client.panels.tabpanel.MinimizableSimplePanel;
import pl.prv.polanie.client.widgets.schedule.Schedule;
import pl.prv.polanie.client.widgets.schedule.widgets.ScheduleCommand;
import pl.prv.polanie.client.widgets.util.GUIUtil;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventPreview;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.MouseListener;
import com.google.gwt.user.client.ui.MouseListenerAdapter;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * Kontrolka używana w drzewku do wszystkich (dla grup, prowadzacych, sal)
 * podziałów, w oknie Schedules.
 */

public class CSObjectHTML extends HTML {
	
	private static String STYLE_OBJECT_HTML = "my-CSObjectHTML";
	private static String STYLE_OBJECT_HTML_HOVERED = "my-CSObjectHTML-hovered";
	
	private static String STYLE_OBJECT_HTML_TOOLTIP = "my-CSObjectHTML-Tooltip";
	
	private static String STYLE_OBJECT_HTML__GROUP = "my-CSObjectHTML-Group";
	private static String STYLE_OBJECT_HTML__LECTURER = "my-CSObjectHTML-Lecturer";
	private static String STYLE_OBJECT_HTML__ROOM = "my-CSObjectHTML-Room";

	private static String STYLE_OBJECT_HTML__GROUP_ALERT = "my-CSObjectHTML-Group-Alert";
	private static String STYLE_OBJECT_HTML__LECTURER_ALERT = "my-CSObjectHTML-Lecturer-Alert";
	private static String STYLE_OBJECT_HTML__ROOM_ALERT = "my-CSObjectHTML-Room-Alert";

	private static String STYLE_OBJECT_HTML__GROUP_YELLOW = "my-CSObjectHTML-Group-Yellow";
	private static String STYLE_OBJECT_HTML__GROUP_RED = "my-CSObjectHTML-Group-Red";

	
	private ICSDTO dto = null;
	
//	private MouseListener tooltipMouseListener
	private Widget tooltipWidget = null; 
	private Timer tooltipTimer = null;
	private PopupPanel tooltipPP = null;
	
	//indicates if widget is red
	private boolean exclamationState = false;
	
	private List<Long> conflictList = null;
	
	private MouseListener mListener = null;
	private EventPreview ePreview = null;
	
	private boolean conflictsPanelVisibleAndAnyConflictSelected = false;


	public CSObjectHTML(ICSDTO dto) {
		super();
		this.dto = dto;
		
		addStyleName(STYLE_OBJECT_HTML);
		
		if (dto instanceof CSGroupDTO) {
			addStyleName(STYLE_OBJECT_HTML__GROUP);
		} else if (dto instanceof CSLecturerDTO) {
			addStyleName(STYLE_OBJECT_HTML__LECTURER);
		} else if (dto instanceof CSRoomDTO) {
			addStyleName(STYLE_OBJECT_HTML__ROOM);
		}
		
		addMouseListener(new MouseListenerAdapter() {
			
			@Override
			public void onMouseEnter(Widget sender) {
				super.onMouseEnter(sender);
				addStyleName(STYLE_OBJECT_HTML_HOVERED);
			}
			
			@Override
			public void onMouseLeave(Widget sender) {
				super.onMouseLeave(sender);
				removeStyleName(STYLE_OBJECT_HTML_HOVERED);
			}
			
		});
	}

	
	public void showExclamationMark() {
		if (!exclamationState) {
			exclamationState = true;
			if (dto instanceof CSGroupDTO) {
				addStyleName(STYLE_OBJECT_HTML__GROUP_ALERT);
			} else if (dto instanceof CSLecturerDTO) {
				addStyleName(STYLE_OBJECT_HTML__LECTURER_ALERT);
			} else if (dto instanceof CSRoomDTO) {
				addStyleName(STYLE_OBJECT_HTML__ROOM_ALERT);
			}
		}
	}
	
	public void hideExclamationMark() {
		if (exclamationState) {
			exclamationState = false;
			if (dto instanceof CSGroupDTO) {
				removeStyleName(STYLE_OBJECT_HTML__GROUP_ALERT);
			} else if (dto instanceof CSLecturerDTO) {
				removeStyleName(STYLE_OBJECT_HTML__LECTURER_ALERT);
			} else if (dto instanceof CSRoomDTO) {
				removeStyleName(STYLE_OBJECT_HTML__ROOM_ALERT);
			}
		}
	}
	
	public void addYellowStyle() {
		addStyleName(STYLE_OBJECT_HTML__GROUP_YELLOW);
	}
	
	public void removeYellowStyle() {
		removeStyleName(STYLE_OBJECT_HTML__GROUP_YELLOW);
	}
	
	public void addRedStyle() {
		addStyleName(STYLE_OBJECT_HTML__GROUP_RED);
	}
	
	public void removeRedStyle() {
		removeStyleName(STYLE_OBJECT_HTML__GROUP_RED);
	}
	
	
	public void removeConflictList() {
		this.conflictList = null;
		
		if (mListener != null) {
			removeMouseListener(mListener);
		}
		this.mListener = null;
		
		if (ePreview != null) {
			DOM.removeEventPreview(ePreview);
		}
		this.ePreview = null;
	}
	
	public void setConflictList(final List<Long> conflictList) {
		removeConflictList();
		
		
		this.conflictList = conflictList;
		
		
		MouseListener mListener = new MouseListenerAdapter() {
			@Override
			public void onMouseEnter(Widget sender) {
				super.onMouseEnter(sender);
				
				if (tooltipTimer == null) {
					tooltipTimer = new Timer() {
						public void run() {
							showConflictsPanel();
						}
					};
				}
				
				tooltipTimer.schedule(500);
			}
			@Override
			public void onMouseLeave(Widget sender) {
				super.onMouseLeave(sender);
				stopListeningWheelEvents();
			}
		};
		
		
		this.mListener = mListener;
		addMouseListener(mListener);
		
	}
	
	private void stopListeningWheelEvents() {
		//usuniecie nasluchiwania rolki myszki
		if (ePreview != null) {
			DOM.removeEventPreview(ePreview);
		}
		CSObjectHTML.this.ePreview = null;
		
		if (tooltipTimer != null) {
			tooltipTimer.cancel();
		}
		if (tooltipPP != null) {
			tooltipPP.hide();
			tooltipPP = null;
		}
		setConflictsPanelVisibleAndAnyConflictSelected(false);
		removeStyleName(STYLE_OBJECT_HTML_HOVERED);
	}
	
	/**
	 * @param conflictList
	 */
	private void showConflictsPanel() {
		if (conflictList != null) {
			
			
			String ce1 = "Subject event ";
			String ce2 = " uses ";
			String ce4 = " already used in other subject event.";
			
			
			final SelectableVerticalPanel svp = new SelectableVerticalPanel(){
				@Override
				protected void runOnLosingHighlightingOnWidget() {
					super.runOnLosingHighlightingOnWidget();
					setConflictsPanelVisibleAndAnyConflictSelected(false);
				}
				@Override
				protected void runOnHighlightingOnWidget() {
					super.runOnHighlightingOnWidget();
					setConflictsPanelVisibleAndAnyConflictSelected(true);
				}
			};
			
			for (int i = 0; i < CSObjectHTML.this.conflictList.size(); i++) {
				Long id = CSObjectHTML.this.conflictList.get(i);

				if (dto instanceof CSGroupDTO) {
					addStyleName(STYLE_OBJECT_HTML__GROUP_ALERT);
					svp.add(new LabelWithId(ce1 + id + ce2 + "subgroup" + ce4, id));
				} else if (dto instanceof CSLecturerDTO) {
					addStyleName(STYLE_OBJECT_HTML__LECTURER_ALERT);
					svp.add(new LabelWithId(ce1 + id + ce2 + "lecturer" + ce4, id));
				} else if (dto instanceof CSRoomDTO) {
					addStyleName(STYLE_OBJECT_HTML__ROOM_ALERT);
					svp.add(new LabelWithId(ce1 + id + ce2 + "room" + ce4, id));
				}
				
			}
			
			
			tooltipWidget = svp;
			
			if (tooltipWidget != null) {
				tooltipPP = new PopupPanel(false, false);
				tooltipPP.addStyleName(STYLE_OBJECT_HTML_TOOLTIP);
				tooltipPP.setWidget(tooltipWidget);
				int left = getAbsoluteLeft() + getOffsetWidth();
				int top = getAbsoluteTop() + getOffsetHeight();
				tooltipPP.setPopupPosition(left, top);
				tooltipPP.setAnimationEnabled(true);
				tooltipPP.show();
			}
			
			
			
			
			//dodanie obslugi rolki myszy
			EventPreview eventPreview = new EventPreview() {
				public boolean onEventPreview(Event event) {
//					Planner.log(".onEventPreview: " + "" + DOM.eventGetTypeString(event));
					if (DOM.eventGetType(event) == Event.ONMOUSEWHEEL) {
						
						int offset = DOM.eventGetMouseWheelVelocityY(event);
						if (offset > 0) {
							
							svp.highlightNextWidget();
						} else {
							svp.highlightPreviousWidget();
						}

						return false;
					} else if (DOM.eventGetType(event) == Event.ONMOUSEOUT) {
						stopListeningWheelEvents();
//						return true;
						} else if (DOM.eventGetType(event) == Event.ONMOUSEMOVE) {
							if (!GUIUtil.eventOverWiget(CSObjectHTML.this, event)) {
								stopListeningWheelEvents();
								return true;
							}
							
						
//					} else if (DOM.eventGetType(event) == Event.BUTTON_RIGHT) {
					} else if ((DOM.eventGetButton(event) & Event.BUTTON_LEFT) != 0 ) {
							if (DOM.eventGetType(event) == Event.ONMOUSEDOWN) {
								Widget w = svp.getHighlightedWidget();
								if (w != null) {
									if (w instanceof LabelWithId) {
										LabelWithId labelWithId = (LabelWithId) w;
										long seID = labelWithId.getId();
										CSSubjectEventDTO csSE = Cache.getCSSubjectEventDTOByID(seID);
										long groupID = CacheService.getGroupIDForGivenSubgroupID(csSE.getSubgroupID());
										
//										Planner.log("BEDE OTWIERAL GRUPE id " + groupID);
										displayGroupAndSelectSubjectEvent(groupID, seID);
									}
								}
								return true;
							}
					}
					return true;
				}
			};
			CSObjectHTML.this.ePreview = eventPreview;
			DOM.addEventPreview(eventPreview);
		}
	};
	
	public void setTooltipWidget(Widget w) {
		if (tooltipTimer != null) {
			tooltipTimer.cancel();
		}
		
		tooltipWidget = w;
	}
	
	
	private void displayGroupAndSelectSubjectEvent(long groupID, final long subjectEventID) {
		
		CSGroupDTO csG = Cache.getCSGroupDTOByID(groupID);
		CSVGroupDTO csvG = ViewDataProvider.getCSVGroup(csG);
		String tabLabel = csvG.toLabelShort();


		CSSemestersYearGroupsDTO csSYG = Cache.getCSSemestersYearGroupsDTOByID(csG.getSemestersYearGroupID());
		Long semesterID = new Long(csSYG.getSemesterID());
		
		
		MinimizableSimplePanel scheduleWrapper = new MinimizableSimplePanel();
//		Planner.getMainHSP().setRightWidget(scheduleWrapper);
		
		
		boolean tabAdded = Planner.getTabPanel().add(scheduleWrapper, "" + tabLabel, "GROUP_" + groupID);
		
		ScheduleCommand scheduleCmd = new ScheduleCommand() {
			public void execute() {
				if (this.getSchedule() != null) {
//					Planner.log("SCHEDULE CMD ZAZNACZY SE!! id => " + subjectEventID);
					this.getSchedule().setSelectedSubjectEventByID(subjectEventID);
					this.getSchedule().setSelectedSubjectEventInTableByID(subjectEventID);
				}
			}
		};
		
		//sciagamy dane do nowootwartej zakladki
		if (tabAdded) {
			SchedulesList.displayScheduleGroupView(scheduleWrapper, groupID, semesterID, scheduleCmd);
		} else {
			//zaznaczamy w otwartej wczesniej zakladce
			Widget w = Planner.getTabPanel().getSelectedWidget();
			SimplePanel sp = (SimplePanel) w;
			Schedule schedule = (Schedule)sp.getWidget();
			schedule.setSelectedSubjectEventByID(subjectEventID);
			schedule.setSelectedSubjectEventInTableByID(subjectEventID);
		}

	}
	
	
	
	public ICSDTO getDto() {
		return dto;
	}

	public void setDto(ICSDTO dto) {
		this.dto = dto;
	}
	
	
//	@Override
//	public void onBrowserEvent(Event event) {
//		super.onBrowserEvent(event);
//		
//		if ((DOM.eventGetButton(event) & Event.BUTTON_RIGHT) != 0 ) {
//			if (DOM.eventGetType(event) == Event.ONMOUSEDOWN) {
//				//DOM.eventCancelBubble(event, true);
//				Planner.log("CSObjectHTML.onBrowserEvent: " + "RIGHT CLICK DOWN");
//				runRightClick();
//			}
//			
//		}
//	}
//	
//	private void runRightClick() {
//		
//	}
	
	
	
	class LabelWithId extends Label {
		Long id = null;

		public LabelWithId(String text, Long id) {
			super(text);
			this.id = id;
		}

		public Long getId() {
			return id;
		}

		public void setId(Long id) {
			this.id = id;
		}
	}


	public boolean isConflictsPanelVisibleAndAnyConflictSelected() {
		return conflictsPanelVisibleAndAnyConflictSelected;
	}


	public void setConflictsPanelVisibleAndAnyConflictSelected(
			boolean conflictsPanelVisibleAndAnyConflictSelected) {
		this.conflictsPanelVisibleAndAnyConflictSelected = conflictsPanelVisibleAndAnyConflictSelected;
	}


}
